import React, {Component} from 'react';
import DeviceCard from '../commons/DeviceCard';
import {CTL_WS_URL, fetchDevices} from '../../api/deviceApi';
import {List, Modal, Toast} from "antd-mobile";
import DeviceController from "../../ws/DeviceController";
import {withStore} from "../../store/storeUtils";
import './Devices.less';
import store from '../../store';

class Devices extends Component {
    state = {
        devices: [],
        loading: false,
    };
    ignoreDisconnectedEvent = false;

    componentDidMount() {
        this.refreshDevices();
        this.deviceController = this.tryInitDeviceController();
        const _this = this;
        this.ignoreDisconnectedEvent = false;
        this.unSubStore = store.subscribe(() => {
            _this.deviceController = _this.tryInitDeviceController();
        });
    }

    refreshDevices() {
        fetchDevices().then(res => {
            const devices = [];
            for (const {weather, device} of res) {
                device.weather = weather;
                device.status = JSON.parse(device.statusJson);
                devices.push(device);
            }
            this.setState({devices: devices});
        });
    }

    componentWillUnmount() {
        this.ignoreDisconnectedEvent = true;
        this.deviceController && this.deviceController.disconnect();
        this.unSubStore();
    }

    tryInitDeviceController() {
        if (this.deviceController) {
            return this.deviceController;
        }
        const {token} = this.props.storeState;
        if (!token.tokenStr) {
            return null;
        }
        console.log('INIT WS with token:', token.tokenStr);
        return this.initDeviceController();
    }

    initDeviceController() {
        const {token} = this.props.storeState;
        const _this = this;
        _this.showMask(true);
        const ctl = new DeviceController({
            token: token.tokenStr,
            url: CTL_WS_URL,
            onConnected: () => _this.showMask(false),
            onDisconnect: () => _this.onControllerDisconnected(),
        });
        ctl.connect();
        return ctl;
    };

    onControllerDisconnected() {
        if (this.ignoreDisconnectedEvent) {
            console.log('Ignore WSClient disconnect!');
            return;
        }
        const _this = this;
        Modal.alert('提示', '服务器断开连接，点击确定重连。', [{
            text: '重连', onPress() {
                _this.deviceController = _this.initDeviceController();
            }
        }]);
    }

    onMotorStateChange = (device, no, state) => {
        const {status} = device;
        let oldState;
        let motor;
        switch (no) {
            case 0:
                oldState = status.motor1;
                motor = 1;
                break;
            case 1:
                oldState = status.motor2;
                motor = 2;
                break;
            default:
                console.log('WARN: can not find motorNo', no);
                return;
        }
        if (oldState === state) {
            return;
        }
        const options = {
            deviceId: device.id,
            status: [
                {
                    motor: motor,
                    state: state,
                }
            ]
        };
        this.deviceCtl(options);
    };

    deviceCtl(options) {
        const _this = this;
        options.onComplete = data => {
            this.showMask(false);
            const {stateCode, responseMsg} = data;
            if (stateCode === 'success') {
                Toast.show('操作成功', 3, false);
                _this.refreshDevices();
            } else {
                Modal.alert('错误：' + stateCode, responseMsg);
            }
        };
        this.showMask(true);
        const success = this.deviceController.deviceCtl(options);
        if (!success) {
            Toast.show('操作太快，请慢一点...', 3, false);
            this.showMask(false);
        }
    }

    showMask(show) {
        this.setState({
            loading: show,
        });
    }

    onDeviceStop = device => {
        const options = {
            deviceId: device.id,
            status: [
                {
                    motor: 1,
                    state: 'off',
                },
                {
                    motor: 2,
                    state: 'off',
                }
            ]
        };
        this.deviceCtl(options);
    };
    onDeviceSettingClick = device => {
        const {id} = device;
        const targetPath = `/device/${id}`;
        this.props.history.push({pathname: targetPath});
    };
    onDeviceWeatherClick = device => {
        const {weather} = device;
        if (!weather) {
            Toast.show('该地区无天气信息！');
            return;
        }
        Modal.alert(weather.title, <List>
            <List.Item extra={weather.title}>天气状态</List.Item>
            <List.Item extra={weather.inRain ? '有雨' : '无雨'}>降雨</List.Item>
            <List.Item extra={weather.temperature}>温度(°C)</List.Item>
            <List.Item extra={weather.humidity}>湿度(%)</List.Item>
            <List.Item>
                地区编码
                <List.Item.Brief>{weather.address}</List.Item.Brief>
            </List.Item>
            <List.Item>
                刷新时间
                <List.Item.Brief>{weather.lastRefreshTime}</List.Item.Brief>
            </List.Item>
        </List>);
    };

    render() {
        const {devices} = this.state;
        return (
            <div className="devices">
                {devices.map(device => <DeviceCard key={device.id}
                                                   device={device}
                                                   onMotorSwitchChange={this.onMotorStateChange}
                                                   onStop={this.onDeviceStop}
                                                   onSettingClick={this.onDeviceSettingClick}
                                                   onWeatherClick={this.onDeviceWeatherClick}/>)}
                {this.renderLoadingMask()}
            </div>
        );
    }

    renderLoadingMask() {
        const {loading} = this.state;
        if (!loading) {
            return null;
        }
        return (<div className="loading-mask">
            <div className="text">等待设备响应......</div>
        </div>);
    }
}

export default withStore(Devices);